﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using FastCtr;
using FastData;

namespace MglMES
{
    public class InterfaceClient
    {
        public static event Action<MglMESBase<object>> OnReceiveMes;
        public static event Action<MglMESBase<object>> OnSendMes;
        public InterfaceClient()
        {
            _newTCP = new NewTCP("MESconnectionStr");
            _newTCP.OnReceiveMessage += new Action<string>(_newTCP_OnReceiveMessage);
            mesInfoConfig = new MesInfoConfig();
            _pLCconnection = new OmroPLC("pLCconnection");
            _pLCconnection.OnPlcReceivedValueChanged += new Action<string, object>(OnPlcReceivedValueChanged);
            _newSQL = new NewSQL("SQLConnection");
            _MesMessageBaseList = new List<MglMESBase<object>>();
            

            Task.Factory.StartNew(() =>
            {
                try
                {
                    _newSQL.StartKeepOnline();
                }
                catch { }
            }, TaskCreationOptions.LongRunning);

            Task.Factory.StartNew(() =>
            {
                _newTCP.Connect();
                _newTCP.StartReceivingMessage();
                bool heartsign = false;
                while (true)
                {
                    try
                    {
                        M001A m001A = new M001A();
                        m001A.ProtocolNO = "1304";
                        m001A.MsgNO = MsgNo;
                        m001A.NeedReply = 1;
                        m001A.CmdID = "001A";
                        m001A.EID = mesInfoConfig.deviceCode.Value;
                        m001A.Data = new List<CHeartbeat>();
                        m001A.Data.Add(new CHeartbeat(1));
                        M001B m001B = M001(m001A);
                        if (m001B == null)
                        {
                            throw new Exception("M001心跳信号超时！");
                        }

                        if (m001B.Data[0].ReturnCode == 0)
                        {
                            outtimeSign = DateTime.Now;
                            Task.Factory.StartNew(() =>
                            {
                                heartsign = !heartsign;
                                _pLCconnection.omron1.Write(mesInfoConfig.heartbeatAdress.Value, heartsign);
                            },TaskCreationOptions.LongRunning);
                        }
                        Thread.Sleep(mesInfoConfig.mesInteractionTime.Value);
                    }
                    catch (Exception exp)
                    {
                       // MessageBox.Show(exp.ToString());
                        Thread.Sleep(1000);
                    }
                }
            }, TaskCreationOptions.LongRunning);

            Task.Factory.StartNew(() =>
            {

                while (true)
                {
                    Thread.Sleep(100);
                    if (DateTime.Now - outtimeSign >= new TimeSpan(0, 0, 0, 0, mesInfoConfig.timeOut.Value))
                    {
                        _mesState = false;
                    }
                    else
                    {
                        _mesState = true;
                    }
                }
            }, TaskCreationOptions.LongRunning);

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    try
                    {
                        Thread.Sleep(1000);
                        TimeSpan timeSpan1 = DateTime.Now - new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, mesInfoConfig.dayTimeOver.Value.Hour, mesInfoConfig.dayTimeOver.Value.Minute, 0);
                        TimeSpan timeSpan2 = DateTime.Now - new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, mesInfoConfig.nightTimeOver.Value.Hour, mesInfoConfig.nightTimeOver.Value.Minute, 0);
                        if (timeSpan1 > new TimeSpan(0, 20, 0) && timeSpan1 < new TimeSpan(0, 50, 0) || timeSpan2 > new TimeSpan(0, 20, 0) && timeSpan2 < new TimeSpan(0, 50, 0))
                        {
                            if (!mesInfoConfig.AlarmUploadSign)
                            {
                                DateTime datetime = DateTime.Now;
                                if (SQLConnectStatus)
                                {
                                    DataSet dataSet = _newSQL.SqlClient.GetDataSet($" SELECT TOP(20) * FROM ( select * from PLC_Alarm_Logs as a where AlertCnt = (select max(AlertCnt) from PLC_Alarm_Logs as b where a.AlertAddress = b.AlertAddress  and [Date]='{mesInfoConfig.shiftDate}' and [ShiftType]='{mesInfoConfig.shift}' ) and [Date]='{mesInfoConfig.shiftDate}' and [ShiftType]='{mesInfoConfig.shift}')  tb order by AlertCnt desc");
                                    if (dataSet.Tables[0].Rows.Count > 0)
                                    {
                                        M402A m402A = new M402A();
                                        m402A.ProtocolNO = "1304";
                                        m402A.MsgNO = MsgNo;
                                        m402A.NeedReply = 1;
                                        m402A.CmdID = "402A";
                                        m402A.EID = mesInfoConfig.deviceCode.Value;
                                        m402A.Data = new List<CEquipmentAlarm>();
                                        for (int k = 0; k < dataSet.Tables[0].Rows.Count; k++)
                                        {
                                            CEquipmentAlarm cEquipmentAlarm = new CEquipmentAlarm();
                                            cEquipmentAlarm.EquipID = mesInfoConfig.deviceCode.Value;
                                            cEquipmentAlarm.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                            cEquipmentAlarm.AlertInfo = dataSet.Tables[0].Rows[k].Field<string>("AlertInfo").ToString();
                                            cEquipmentAlarm.AlertCnt = dataSet.Tables[0].Rows[k].Field<int>("AlertCnt").ToString();
                                            cEquipmentAlarm.Date = dataSet.Tables[0].Rows[k].Field<DateTime>("Date").ToString("yyyy-MM-dd");
                                            cEquipmentAlarm.ShiftType = dataSet.Tables[0].Rows[k].Field<string>("ShiftType").ToString();
                                            m402A.Data.Add(cEquipmentAlarm);
                                        }
                                        M402B m402B = M402(m402A);
                                        if (m402B != null)
                                        {
                                            if (m402B.Data[0].ReturnCode == 0)
                                            {
                                                mesInfoConfig.AlarmUploadSign = true;
                                            }
                                            else
                                            {

                                            }
                                        }
                                        else
                                        {

                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            mesInfoConfig.AlarmUploadSign = false;
                        }
                    }
                    catch
                    {

                    }
                }
            }, TaskCreationOptions.LongRunning);



            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    try
                    {
                        if (SQLConnectStatus)
                        {
                            DataSet dataSetcount = _newSQL.SqlClient.GetDataSet("select count(*) from tbresult");
                            int count = (int)dataSetcount.Tables[0].Rows[0][0];
                            if (count != 0)
                            {
                                DataSet dataSetData = _newSQL.SqlClient.GetDataSet("select * from tbresult where 0=0");
                                for (int i = 0; i < dataSetData.Tables[0].Rows.Count; i++)
                                {
                                    M709A m709A = new M709A();
                                    m709A.ProtocolNO = "1304";
                                    m709A.MsgNO = MsgNo;
                                    m709A.NeedReply = 1;
                                    m709A.CmdID = "709A";
                                    m709A.EID = mesInfoConfig.deviceCode.Value;
                                    m709A.Data = new List<CEquipmentStatistic>();
                                    CEquipmentStatistic cEquipmentStatistic = new CEquipmentStatistic();
                                    cEquipmentStatistic.EquipID = mesInfoConfig.deviceCode.Value;
                                    cEquipmentStatistic.CellID = dataSetData.Tables[0].Rows[i].Field<string>("条码");
                                    cEquipmentStatistic.BeginTime = dataSetData.Tables[0].Rows[i].Field<DateTime>("时间").ToString("yyyy-MM-dd HH:mm:ss");
                                    cEquipmentStatistic.DateTime = dataSetData.Tables[0].Rows[i].Field<DateTime>("时间").ToString("yyyy-MM-dd HH:mm:ss");
                                    cEquipmentStatistic.ElcLotID = dataSetData.Tables[0].Rows[i].Field<string>("电解液批次号");
                                    cEquipmentStatistic.EndTime = dataSetData.Tables[0].Rows[i].Field<DateTime>("时间").ToString("yyyy-MM-dd HH:mm:ss");
                                    cEquipmentStatistic.InjectVac = dataSetData.Tables[0].Rows[i].Field<string>("注液腔真空度");
                                    cEquipmentStatistic.InjectWeight1st = "0";
                                    cEquipmentStatistic.InjectWeight2nd = dataSetData.Tables[0].Rows[i].Field<string>("注液量");
                                    cEquipmentStatistic.LosePercent = "0";
                                    cEquipmentStatistic.Process = "1";
                                    cEquipmentStatistic.Result = dataSetData.Tables[0].Rows[i].Field<string>("OK/NG");
                                    if (cEquipmentStatistic.Result.ToUpper() == "OK")
                                    {
                                        cEquipmentStatistic.NGReason = "";
                                    }
                                    else
                                    {
                                        cEquipmentStatistic.NGReason = "注液NG";
                                    }
                                    cEquipmentStatistic.SealPress = dataSetData.Tables[0].Rows[i].Field<string>("封装压力");
                                    cEquipmentStatistic.SealTemp = dataSetData.Tables[0].Rows[i].Field<string>("封装温度");
                                    cEquipmentStatistic.SealTime = dataSetData.Tables[0].Rows[i].Field<string>("封装时间");
                                    cEquipmentStatistic.UserID = dataSetData.Tables[0].Rows[i].Field<string>("员工工号");
                                    cEquipmentStatistic.VacStandPress = dataSetData.Tables[0].Rows[i].Field<string>("注液后静置真空度");
                                    cEquipmentStatistic.VacStandTime = dataSetData.Tables[0].Rows[i].Field<string>("注液后静置时间");
                                    cEquipmentStatistic.WeighAfterInject = dataSetData.Tables[0].Rows[i].Field<string>("后称");
                                    cEquipmentStatistic.WeighBeforeInject = dataSetData.Tables[0].Rows[i].Field<string>("前称");
                                    cEquipmentStatistic.WeighAfterSeal = dataSetData.Tables[0].Rows[i].Field<string>("后称");
                                    m709A.Data.Add(cEquipmentStatistic);
                                    M709B m709B = InterfaceClient.M709(m709A);
                                    if (m709B.Data[0].ReturnCode == 0)
                                    {
                                        if (SQLConnectStatus)
                                        {
                                            _newSQL.SqlClient.InsertData($"insert into [tbresult_copy]  select * from [tbresult] where [tbresult].[条码]='{cEquipmentStatistic.CellID}'");
                                            _newSQL.SqlClient.DeleteData("tbresult", new string[] { "条码" }, new object[] { cEquipmentStatistic.CellID });
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch { }
                    Thread.Sleep(1000);
                }
            }, TaskCreationOptions.LongRunning);
        }


        public static void DoWork()
        {
            Current = new InterfaceClient();
        }


        public static void SetSocketConnectionForm()
        {
            Form form = new Form();
            form.Controls.Add(_newTCP);
            form.ShowDialog();
        }


        public static void SetMESInfoConfigForm()
        {
            Form form = new Form();
            form.Controls.Add(mesInfoConfig);
            form.ShowDialog();
        }

        public static void SetPLCConnectionForm()
        {
            Form form = new Form();
            form.Controls.Add(_pLCconnection);
            form.ShowDialog();
        }

        public static void SetSQLConnectionForm()
        {
            Form form = new Form();
            form.Controls.Add(_newSQL);
            form.ShowDialog();
        }

        private void _newTCP_OnReceiveMessage(string receiveString)
        {
            long k = 0;
            MglMESBase<object> mglMESBase = receiveString.FromJSON<MglMESBase<object>>();
            MesMessageBaseList.Add(mglMESBase);

            OnReceiveMes?.Invoke(mglMESBase);

            if (SQLConnectStatus)
            {
                _newSQL.SqlClient.Insert("Json_log", new string[] { "InterfaceName", "Json" }, new object[] { mglMESBase.CmdID, mglMESBase.ToJSON() }, ref k);
            }
        }

        /// <summary>
        /// 此处用于记录PLC报警，并上传到MES
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        private void OnPlcReceivedValueChanged(string name, object value)
        {
            try
            {
                //把PLC的所有报警记录到本地，包括发生时间和恢复时间
                if (mesInfoConfig.plcAlarmAddressList.Value.Where(t => name.Contains(t)).FirstOrDefault() != null)
                {
                    if ((bool)value)
                    {
                        long id = 0;
                        if (SQLConnectStatus)
                        {
                            _newSQL.SqlClient.Insert("PLC_Alarm_Logs", new string[] { "EquipID", "ShiftType", "AlertAddress" }, new object[] { mesInfoConfig.deviceCode.Value, mesInfoConfig.shift, name }, ref id);
                        }
                    }
                    //else
                    //{
                    //    if (SQLConnectStatus)
                    //    {
                    //        if (_newSQL.connectType == NewSQL.ConnectType.SqlServer)
                    //        {
                                
                    //            _newSQL.SqlClient.Update($"update [PLC_Alarm_Logs] set [DateTimeDis]='{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}' where [Index] =(SELECT TOP 1 [Index] FROM [PLC_Alarm_Logs] where [AlertAddress] ='{name}' order by [Index] desc)");
                    //        }
                    //        else
                    //        {
                    //            _newSQL.SqlClient.Update($"update PLC_Alarm_Logs set DateTimeDis=\"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}\"  where [Index] =(SELECT TOP 1 [Index] FROM [PLC_Alarm_Logs] where [AlertAddress] ='{name}' order by [Index] desc)");
                    //        }
                    //    }
                    //}
                }

                if (MESConnectStatus)
                {
                    //记录设备的运行状态  1. 运行；2. 待机； 3.故障；4.维修 ；5.停机；
                    if (name == mesInfoConfig.devicestateAdress.Value)
                    {
                        M101A m101A = new M101A();
                        m101A.ProtocolNO = "1304";
                        m101A.MsgNO = MsgNo;
                        m101A.NeedReply = 1;
                        m101A.CmdID = "101A";
                        m101A.EID = mesInfoConfig.deviceCode.Value;
                        m101A.Data = new List<CEquipmentStatus>();
                        CEquipmentStatus cEquipmentStatus = new CEquipmentStatus();
                        cEquipmentStatus.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        cEquipmentStatus.EquipID = mesInfoConfig.deviceCode.Value;
                        cEquipmentStatus.Status = value.ToString();
                        m101A.Data.Add(cEquipmentStatus);
                        M101B m101B = M101(m101A);
                        if (m101B == null)
                        {
                            throw new Exception($"M101状态信息上传超时！详细：{m101A.ToJSON()}");
                        }
                        if (m101B.Data[0].ReturnCode == 0)
                        {
                            // MessageBox.Show($"状态信息上传成功！详细：{m101A.ToJSON()} 收到回复信息{m101B.ToJSON()}");
                        }
                    }
                }
            }
            catch
            {

            }
        }




        private static T ExChangeInfo<T>(MglMESBase<object> obj)
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);
            autoResetEvent.Reset();
            T m = default(T);
            _newTCP.SendMessage(obj.ToJSON() + "\r\n", false);
            OnSendMes?.Invoke(obj);
            long k = 0;
            if (SQLConnectStatus)
            {
                _newSQL.SqlClient.Insert("Json_log", new string[] { "InterfaceName", "Json" }, new object[] { obj.CmdID, obj.ToJSON() }, ref k);
            }
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    int count = MesMessageBaseList.Count;
                    MglMESBase<object>[] MesMessageBaseArry = new MglMESBase<object>[count];
                    MesMessageBaseList.CopyTo(0, MesMessageBaseArry, 0, count);
                    MglMESBase<object> mglMESBase = MesMessageBaseArry.Where(t => t.MsgNO == obj.MsgNO).FirstOrDefault();
                    if (mglMESBase != null)
                    {
                        m = mglMESBase.ToJSON().FromJSON<T>();

                        if (autoResetEvent == null)
                        {
                            break;
                        }
                        else
                        {
                            autoResetEvent.Set();

                        }
                        break;
                    }
                    Thread.Sleep(10);
                }
            });
            if (autoResetEvent.WaitOne(mesInfoConfig.timeOut.Value))
            {
                autoResetEvent.Close();
                autoResetEvent.Dispose();
                autoResetEvent = null;
                GC.Collect();
              
                return m;
            }
            else
            {
                autoResetEvent.Close();
                autoResetEvent.Dispose();
                autoResetEvent = null;
                GC.Collect();
                return default(T);
            }
        }



        /// <summary>
        /// 心跳消息，向服务端标识设备在线
        /// </summary>
        public static M001B M001(M001A obj)
        {
            return ExChangeInfo<M001B>(obj.ToJSON().FromJSON<MglMESBase<object>>());
        }

        /// <summary>
        /// 设备状态信息上报
        /// </summary>
        /// 
        public static M101B M101(M101A obj)
        {
            return ExChangeInfo<M101B>(obj.ToJSON().FromJSON<MglMESBase<object>>());
        }

        /// <summary>
        /// 设备报警信息 Top20 上报
        /// </summary>
        /// 
        public static M402B M402(M402A obj)
        {
            return ExChangeInfo<M402B>(obj.ToJSON().FromJSON<MglMESBase<object>>());
        }


        /// <summary>
        /// 设备生产结果数据上报
        /// </summary>
        /// 
        public static M709B M709(M709A obj)
        {
            return ExChangeInfo<M709B>(obj.ToJSON().FromJSON<MglMESBase<object>>());
        }






        public static InterfaceClient Current;
        static List<MglMESBase<object>> _MesMessageBaseList;   //当前程序收到的所有短消息
        static bool _mesState;
        public static NewTCP _newTCP;
      
        public  static MesInfoConfig mesInfoConfig;
        public static OmroPLC _pLCconnection;
        public static NewSQL _newSQL;
        static int msgno = 0;
        static object msg_lock = new object();
        static DateTime outtimeSign = DateTime.Now - new TimeSpan(0, 0, 10);
        public static bool AlarmUpLoadSign = false;

        public static bool PLCConnectStatus
        {
            get
            {
                if (_pLCconnection != null)
                    return _pLCconnection.State;
                else
                    return false;
            }
        }

        public static bool MESConnectStatus
        {
            get
            {
                return _mesState;
            }
        }

        public static bool SQLConnectStatus
        {
            get
            {
                if (_newSQL != null)
                    return _newSQL.State;
                else
                    return false;

            }
        }

        public static int MsgNo
        {
            get
            {
                lock (msg_lock)
                {
                    msgno++;
                    if (msgno == 99999 + 1)
                    {
                        msgno = 0;
                    }
                }
                return msgno;
            }

        }

        public static object lock_meslist = new object();
        public static List<MglMESBase<object>> MesMessageBaseList
        {
            get
            {
                lock (lock_meslist)
                {
                    if (_MesMessageBaseList.Count > 100)
                    {
                        _MesMessageBaseList.RemoveAt(0);
                    }
                
                    return _MesMessageBaseList;
                }
            }
    
        }


    }


    //[Serializable]
    //public class AlarmUploadLogClass
    //{
    //    public AlarmUploadLogClass(string date, string shift)
    //    {
    //        Date = date;
    //        Shift = shift;
    //    }
    //    public string Date;
    //    public string Shift;
    //    public bool isUPloaded = false;
    //}

    public class MessageEventArgs : EventArgs
    {
        public MessageEventArgs(string message)
        {
            Messsage = message;
        }
        public string Messsage;
    }
}